#ifndef BIO_PH_SOLUTION_INCLUDED
#define BIO_PH_SOLUTION_INCLUDED 1

#include "kernel/initializer.hpp"
#include "yocto/ios/ostream.hpp"

class Component
{
public:
	Real           C;        //!< concentration
	const Species &species;  //!< in library
	
	Component( const Library &library, const string &name );
	~Component() throw();
	
	Component( const Component &other ) throw();
	
	const string & key() const throw();
	
private:
	YOCTO_DISABLE_ASSIGN(Component);
};


typedef set<string,Component> ComponentSet;
class Solution 
{
public:
	explicit Solution( const Library & );
	virtual ~Solution() throw();
	
	
	Real & operator[]( const string & );
	Real & operator[]( size_t ) throw();
	const Real & operator[]( const string & ) const;
	const Real & operator[]( size_t ) const throw();
	
	const Species & operator()( const string & ) const;
	const Species & operator()( size_t ) const throw();
	
	void load( const array<Real> & );
	void save( array<Real> &) const;
	
	
	void load_from( const ChemSys &chemsys );
	void save_into( ChemSys &chemsys ) const;
	
	void display( std::ostream &fp ) const;
	void mul( Real a ) throw();
	
	Real pH() const;
	
	void zero() throw();
	
	//! passive fluxes
	void addLeak( const Real zeta_m, const Real CellVolume, const Solution &in, const Solution &out );
	
	//! compute dLeak/dzeta and return sum of Z_x * dLeak/dzeta
	Real set_dLeak_dzeta( const Real zeta_m, const Real CellVolume, const Solution &in, const Solution &out);
	
	
	Real sumCharge() const throw();
	
	void write_header( ios::ostream &fp ) const;
	void write_values( ios::ostream &fp, const char *fmt ) const;	
	
private:
	ComponentSet components_;
	
public:
	const size_t   size;
	const Library &library;
};


#endif
